package com.framework.apollo;

import com.ctrip.framework.apollo.Config;
import com.ctrip.framework.apollo.ConfigChangeListener;
import com.ctrip.framework.apollo.ConfigService;
import com.ctrip.framework.apollo.model.ConfigChangeEvent;
import com.github.wnameless.json.flattener.JsonFlattener;
import com.github.wnameless.json.unflattener.JsonUnflattener;
import net.sf.json.JSONSerializer;
import net.sf.json.xml.XMLSerializer;
import org.dom4j.Document;
import org.dom4j.DocumentException;
import org.dom4j.DocumentHelper;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.logging.LoggerConfiguration;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * 处理key-value格式的配置文件信息
 */
@Service
public class PropertyConfiguration {
    private static final Logger logger = LoggerFactory.getLogger(LoggerConfiguration.class);
    @Value("${apollo.cacheDir}")
    private String filePath;

    @Value("${apollo.namespace}")
    private String  namespace;

    @Value("${app.id}")
    private String appId;

    @Value("${apollo.cluster}")
    private String cluster;

    @PostConstruct
    private void change(){
        //遍历namesapce，添加change监听事件，更新xml文件
        if(namespace==null||"".equals(namespace)) {
            namespace="application";
        }
        String[] namespaces=namespace.split(",");
        for(int i=0;i<namespaces.length;i++) {
            String space=namespaces[i];
            Config config = ConfigService.getConfig(namespaces[i]);
            config.addChangeListener(new ConfigChangeListener() {
                @Override
                public void onChange(ConfigChangeEvent configChangeEvent) {
                    refreshXmlFiles(space);
                }
            });
        }
    }

    @PostConstruct
    private void initXmlFiles(){
        //遍历namesapce，添加change监听事件，更新xml文件
        if(namespace==null||"".equals(namespace)) {
            namespace="application";
        }
        String[] namespaces=namespace.split(",");
        for(int i=0;i<namespaces.length;i++) {
            String space = namespaces[i];
            refreshXmlFiles(space);
        }
    }

    //更新xml文件
    private void refreshXmlFiles(String namespace)  {
        String xmlContent="";
        Map<String,Object> keyValues=new HashMap<>();
        Config config = ConfigService.getConfig(namespace);
        Set<String> keyNames = config.getPropertyNames();
        for (String key : keyNames) {
            String value = config.getProperty(key, "");
            key=replaceLast(key,"\\.",".@");//处理<key   value=''> 在json里，value需要更新为@value
            keyValues.put(key,value);
        }
        if(!keyValues.isEmpty()) {
            JSONObject json = new JSONObject(keyValues);
            System.out.println("去扁平化处理之前,json数据："+json.toString());
            String unflattenJson = JsonUnflattener.unflatten(json.toString());
            System.out.println("去扁平化处理之后,json数据："+unflattenJson);
            JSONObject json2 = new JSONObject(unflattenJson);
            xmlContent = json2xml(unflattenJson);
            System.out.println("json转xml后数据："+xmlContent);
            FileWriter fwriter = null;
            try {
                File file = new File(filePath + "/" + appId + "/" + cluster);
                if (!file.exists()) {
                    file.mkdirs();
                }
                // true表示不覆盖原来的内容，而是加到文件的后面。若要覆盖原来的内容，直接省略这个参数就好
                fwriter = new FileWriter(filePath + "/" + appId + "/" + cluster + "/" + namespace+ ".xml", false);
                fwriter.write(xmlContent);
            } catch (IOException ex) {
                ex.printStackTrace();
            } finally {
                try {
                    fwriter.flush();
                    fwriter.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
    //处理配置文件内容为xml格式
    private String prop2Xml(String fileContent) {
        return null;
    }
    /**
     * JSON(数组)字符串转换成XML字符串
     * （必须引入 xom-1.1.jar）
     * @param jsonString
     * @return
     */
    public static String json2xml(String jsonString) {
        StringBuffer sb = new StringBuffer();
        String xmlStr = "";

        XMLSerializer xmlSerializer = new XMLSerializer();
        xmlSerializer.setTypeHintsEnabled(false);//设置生成的xml，标签里没有class="object",type="string"类型属性
        String xml=xmlSerializer.write(JSONSerializer.toJSON(jsonString));
        xml = xml.replace("<o>", "").replace("</o>", "");//去除最外层标签默认<o>
        Document document;

        try {
            document = DocumentHelper.parseText(xml);
            xmlStr = document.getRootElement().asXML();
        } catch (DocumentException e) {
            e.printStackTrace();
        }
        sb.append("<?xml version=\"1.0\" encoding=\"gb2312\" standalone=\"no\" ?>")
                .append(xmlStr);
        xmlStr=sb.toString().replace("><",">\n<");
        return xmlStr;
    }

    // 替换字符串里最后出现的元素
    public static String replaceLast( String text, String strToReplace,
                                      String replaceWithThis ) {
        if(text.contains(".")){
            return text.replaceFirst( "(?s)" + strToReplace + "(?!.*?" + strToReplace
                    + ")", replaceWithThis );
        }else{
            return text;
        }

    }
}
